package cn.wen233.srpc.core.server.impl;

import cn.wen233.srpc.basic.utils.ThreadPoolUtils;
import cn.wen233.srpc.core.server.AbstractServer;
import cn.wen233.srpc.core.server.handletask.SerializeTask;
import cn.wen233.srpc.core.service.SunglowServiceScan;
import cn.wen233.srpc.core.service.SunglowServiceScanHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;

/**
 * 原生socket服务端
 * 使用Java ServerSocket实现服务端
 * 阻塞IO
 *
 * @author wenei
 * @date 2021-10-28 21:15
 */
public class NativeSocketServer extends AbstractServer {

    private static final Logger LOGGER = LoggerFactory.getLogger(NativeSocketServer.class);

    private ExecutorService workThreadPool = ThreadPoolUtils.newCoreThreadPool();

    private ExecutorService acceptThreadPool = ThreadPoolUtils.newSingleThreadPool();

    private ServerSocket serverSocket;

    private volatile boolean run = true;

    /**
     * 获取最底层栈帧，也就是main方法所在的类
     * 处理其上的@SunglowServiceScan注解
     */
    @Override
    public void init() {
        try {
            // 扫描注解
            final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            Class<?> bootClass = Class.forName(stackTrace[stackTrace.length - 1].getClassName());
            if (bootClass.isAnnotationPresent(SunglowServiceScan.class)) {
                SunglowServiceScan sunglowServiceScan = bootClass.getDeclaredAnnotation(SunglowServiceScan.class);
                SunglowServiceScanHandler.handle(sunglowServiceScan.path(), false);
            }
            // 创建Socket
            serverSocket = new ServerSocket(port);
        } catch (ClassNotFoundException | IOException e) {
            LOGGER.error("初始化SocketServer时出现异常", e);
        }
        // 关闭回调函数
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            LOGGER.info("{} 服务端退出", this.getClass().getName());
            workThreadPool.shutdownNow();
            acceptThreadPool.shutdownNow();
        }));
    }

    @Override
    protected void service() {
        acceptThreadPool.execute(() -> {
            while (run) {
                Socket socket = null;
                try {
                    socket = serverSocket.accept();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                workThreadPool.execute(new SerializeTask(socket));
            }
        });
        LOGGER.info("{} 服务端启动完成", this.getClass().getName());
    }
}
